#include <lvgl.h>
#include <TFT_eSPI.h>
#include <Arduino.h>
#include <SPI.h>
#include <TFT_Touch.h>
#include <stdio.h>
#include "myapps.h"

#define LVGL_TICK_PERIOD 60
#define TFT_BL 22

TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];

lv_obj_t *slider_label;
int screenWidth = 320;
int screenHeight = 240;

//触摸
#define DOUT 14 /* Data out pin (T_DO) of touch screen */
#define DIN 27  /* Data in pin (T_DIN) of touch screen */
#define DCS 26  /* Chip select pin (T_CS) of touch screen */
#define DCLK 25 /* Clock pin (T_CLK) of touch screen */
TFT_Touch touch = TFT_Touch(DCS, DCLK, DIN, DOUT);
int X_Raw = 0, Y_Raw = 0;

#define TOUCH_DELAY delay(200)

#if USE_LV_LOG != 0
/* Serial debugging */
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *dsc)
{

    Serial.printf("%s@%d->%s\r\n", file, line, dsc);
    delay(100);
}
#endif

/**称重**/
String rec_str;
int quality = 0;
int qual_pos = 100;
int qual_endpos = 100;

/***电机***/
#define ACT_PUSH 1
#define ACT_POP 0
int M1_step = 1;
int M1_dir = 1;
String M1_str;
bool M1_sw_state = false;
bool M1_dir_state = false;

int M2_act = 3;
String M2_str;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    uint16_t c;

    tft.startWrite();                                                                            /* Start new TFT transaction */
    tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
    for (int y = area->y1; y <= area->y2; y++)
    {
        for (int x = area->x1; x <= area->x2; x++)
        {
            c = color_p->full;
            tft.writeColor(c, 1);
            color_p++;
        }
    }
    tft.endWrite();            /* terminate TFT transaction */
    lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}

bool my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
    uint16_t touchX, touchY;

    bool touched = touch.Pressed(); //检测触摸是否按下
    //获取屏幕坐标
    touchX = touch.X() * 1.08;
    touchY = touch.Y();

    if (!touched)
    {
        return false;
    }

    if (touchX > screenWidth || touchY > screenHeight)
    {
        // Serial.println("Y or y outside of expected parameters..");
        // Serial.print("y:");
        // Serial.print(touchX);
        // Serial.print(" x:");
        // Serial.print(touchY);
    }
    else
    {

        data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;

        /*Save the state and save the pressed coordinate*/
        // if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);

        /*Set the coordinates (if released use the last pressed coordinates)*/
        data->point.x = touchX;
        data->point.y = touchY;

        // Serial.print("Data x");
        // Serial.println(touchX);

        // Serial.print("Data y");
        // Serial.println(touchY);
    }

    return false; /*Return `false` because we are not buffering and no more data to read*/
}

/***全局***/
long date = 0;
uint8_t date_cotter = 0;
lv_obj_t *gauge1;
lv_obj_t *HX_value_lab1;
lv_obj_t *M1_dir_btn;
lv_obj_t *M1_sw_btn;
lv_obj_t *M2_pop_btn;
lv_obj_t *M2_push_btn;
lv_obj_t *M1_dir_lab;
lv_obj_t *M1_sw_lab;
lv_obj_t *M2_pop_lab;
lv_obj_t *M2_push_lab;
lv_obj_t *M1_step_slider;
lv_obj_t *M1_step_lab;

static void M1_dir_btn_event_cb(lv_obj_t *obj, lv_event_t e);
static void M1_sw_btn_event_cb(lv_obj_t *obj, lv_event_t e);
static void M2_pop_btn_event_cb(lv_obj_t *obj, lv_event_t e);
static void M2_push_btn_event_cb(lv_obj_t *obj, lv_event_t e);
static void M1_step_slider_event_cb(lv_obj_t *obj, lv_event_t e);

void setup()
{
    Serial.begin(115200); /* prepare for possible serial debug */
    //Serial2.begin(15200);
    //屏幕背光采用PWM调光
    ledcSetup(10, 5000 /*freq*/, 10 /*resolution*/);
    ledcAttachPin(TFT_BL, 10);
    analogReadResolution(10);
    ledcWrite(10, 1023);
    //delay(1000);
    lv_init();

#if USE_LV_LOG != 0
    lv_log_register_print_cb(my_print); /* register print function for debugging */
#endif
    //屏幕初始化
    tft.begin(); /* TFT init */
    tft.setRotation(1);
    //触摸初始化
    touch.setCal(481, 3395, 755, 3487, 320, 240, 1);
    // touch.setCal(0, 4095, 0, 4095, 320, 240, 1);//, 0, 0);
    //旋转
    touch.setRotation(3);
    lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

    //显示刷新接口
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.buffer = &disp_buf;
    lv_disp_drv_register(&disp_drv);

    //触摸板输入接口
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);          /*Descriptor of a input device driver*/
    indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
    indev_drv.read_cb = my_touchpad_read;   /*Set your driver function*/
    lv_indev_drv_register(&indev_drv);      /*Finally register the driver*/

    date = millis();
    //放置仪表盘控件
    static lv_color_t needle_colors[1];
    needle_colors[0] = LV_COLOR_PURPLE;
    // gauge控件
    gauge1 = lv_gauge_create(lv_scr_act(), NULL);
    lv_gauge_set_needle_count(gauge1, 1, needle_colors);
    lv_obj_set_size(gauge1, 150, 150);
    lv_obj_align(gauge1, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
    //设置仪表指针指向的值
    lv_gauge_set_critical_value(gauge1, 80); //设置关键数值点，默认80
    lv_gauge_set_value(gauge1, 0, 0);
    lv_gauge_set_range(gauge1, 0, 100);
    lv_gauge_set_scale(gauge1, 300, 31, 6);
    // static lv_style_t gauge_style;
    // gauge_style.body.padding.left = 10; /*刻度条的长度*/
    // gauge_style.body.padding.inner = 8; /*文本与刻度条的距离*/

    // lv_obj_add_style(gauge1,LV_STYLE_PART_MAIN, &gauge_style);
    //
    /**
      lv_gauge_set_range(gauge1, 0, 80);//设置仪表盘数值范围，默认0-100
      lv_gauge_set_critical_value(gauge1, 60);//设置关键数值点，默认80
      lv_gauge_set_needle_count(gauge1, 3, needle_colors);//设置指针数量和颜色

    */

    // isky add
    HX_value_lab1 = lv_label_create(gauge1, NULL);
    lv_obj_align(HX_value_lab1, gauge1, LV_ALIGN_IN_BOTTOM_MID, 5, -2);
    lv_label_set_text(HX_value_lab1, "-1g");

    M1_dir_btn = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_size(M1_dir_btn, 73, 55);
    lv_obj_set_pos(M1_dir_btn, 160, 95);
    lv_obj_set_event_cb(M1_dir_btn, M1_dir_btn_event_cb);
    M1_dir_lab = lv_label_create(M1_dir_btn, NULL);
    lv_obj_align(M1_dir_lab, M1_dir_btn, LV_ALIGN_CENTER, 2, -2);
    lv_label_set_text(M1_dir_lab, "positive"); //positive and negative

    M1_sw_btn = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_size(M1_sw_btn, 73, 55);
    lv_obj_set_pos(M1_sw_btn, 243, 95);
    lv_obj_set_event_cb(M1_sw_btn, M1_sw_btn_event_cb);
    M1_sw_lab = lv_label_create(M1_sw_btn, NULL);
    lv_obj_align(M1_sw_lab, M1_sw_btn, LV_ALIGN_CENTER, 0, 0);
    lv_label_set_text(M1_sw_lab, "off");

    M2_pop_btn = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_size(M2_pop_btn, 73, 55);
    lv_obj_set_pos(M2_pop_btn, 160, 165);
    lv_obj_set_event_cb(M2_pop_btn, M2_pop_btn_event_cb);
    M2_pop_lab = lv_label_create(M2_pop_btn, NULL);
    lv_obj_align(M2_pop_lab, M2_pop_btn, LV_ALIGN_CENTER, 0, 0);
    lv_label_set_text(M2_pop_lab, "pop");

    M2_push_btn = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_size(M2_push_btn, 73, 55);
    lv_obj_set_pos(M2_push_btn, 243, 165);
    lv_obj_set_event_cb(M2_push_btn, M2_push_btn_event_cb);
    M2_push_lab = lv_label_create(M2_push_btn, NULL);
    lv_obj_align(M2_push_lab, M2_push_btn, LV_ALIGN_CENTER, 0, 0);
    lv_label_set_text(M2_push_lab, "push");

    M1_step_slider = lv_slider_create(lv_scr_act(), NULL);
    lv_obj_set_size(M1_step_slider, 240, 25);
    lv_obj_align(M1_step_slider, lv_scr_act(), LV_ALIGN_IN_TOP_MID, -5, 20);
    lv_slider_set_range(M1_step_slider, 1, 7);
    lv_slider_set_value(M1_step_slider, 3, LV_ANIM_OFF);
    lv_obj_set_event_cb(M1_step_slider, M1_step_slider_event_cb);

    M1_step_lab = lv_label_create(M1_step_slider, NULL);
    lv_obj_align(M1_step_lab, M1_step_slider, LV_ALIGN_CENTER, 20, 0);
    lv_label_set_text(M1_step_lab, "3");
    //lv_slider_get_value(slider)
    M1_step = 3;
    Serial2.begin(19200);
    // Serial2.println();
    delay(10);
}

void loop()
{
    lv_task_handler(); /* let the GUI do its work */
    // Serial.println("loop");
    while (Serial2.available())
    {
        delay(2);
        rec_str = Serial2.readStringUntil('\n');
    }
    //处理数据
    if (rec_str.length() > 0)
    {
        rec_str.trim();
        // Serial.println(rec_str);
        if (rec_str.indexOf("HX:") != -1)
        {
            qual_pos = rec_str.indexOf("HX:");
            qual_endpos = rec_str.indexOf("END");
            quality = rec_str.substring(qual_pos + 3, qual_endpos - qual_pos).toInt();
        }
        char temp_quality[20];
        sprintf(temp_quality, "%dg", quality);
        lv_label_set_text(HX_value_lab1, temp_quality);
        date_cotter = quality / 50;
        date_cotter = testfile(date_cotter);
        lv_gauge_set_value(gauge1, 0, date_cotter);
        rec_str = "";
    }
}

static void M1_dir_btn_event_cb(lv_obj_t *obj, lv_event_t e)
{
    if (e == LV_EVENT_RELEASED)
    {
        if (M1_dir_state)
        {
            M1_dir = 1;
            //positive and negative
            M1_dir_state = false;
            if (!M1_sw_state)
            {
                M1_str = String("M1:") + String(M1_step) + "dir:" + String(M1_dir);
                Serial2.println(M1_str);
                Serial.println(M1_str);
            }
            else
            {
                M1_str = String("M1:") + String(0) + "dir:" + String(M1_dir);
                Serial2.println(M1_str);
                Serial.println(M1_str);
            }
            lv_label_set_text(M1_dir_lab, "positive");
            Serial.print("M1_dir:positive");
        }
        else
        {
            M1_dir = 0;
            M1_dir_state = true;
            if (!M1_sw_state)
            {
                M1_str = String("M1:") + String(M1_step) + "dir:" + String(M1_dir);
                Serial2.println(M1_str);
                Serial.println(M1_str);
            }
            else
            {
                M1_str = String("M1:") + String(0) + "dir:" + String(M1_dir);
                Serial2.println(M1_str);
                Serial.println(M1_str);
            }
            lv_label_set_text(M1_dir_lab, "negative");
            Serial.print("M1_dir:negative");
        }
        TOUCH_DELAY;
    }
}
static void M1_sw_btn_event_cb(lv_obj_t *obj, lv_event_t e)
{
    if (e == LV_EVENT_RELEASED)
    {
        // M1_step = lv_slider_get_value(M1_step_slider);
        if (M1_sw_state)
        {
            M1_str = String("M1:") + String(M1_step) + "dir:" + String(M1_dir);
            Serial2.println(M1_str);
            Serial.println(M1_str);
            lv_label_set_text(M1_sw_lab, "on");
            M1_sw_state = false;
        }
        else
        {
            M1_str = String("M1:") + String(0) + "dir:" + String(M1_dir);
            Serial2.println(M1_str);
            Serial.println(M1_str);
            lv_label_set_text(M1_sw_lab, "off");
            M1_sw_state = true;
        }
        TOUCH_DELAY;
    }
}
static void M2_pop_btn_event_cb(lv_obj_t *obj, lv_event_t e)
{
    if (e == LV_EVENT_RELEASED)
    {
        M2_str = String("M2:") + String(ACT_POP);
        // //对象被按下时触发,每次按下时只触发一次
        Serial2.println(M2_str);
        Serial.println(M2_str);
        TOUCH_DELAY;
    }
}
static void M2_push_btn_event_cb(lv_obj_t *obj, lv_event_t e)
{
    if (e == LV_EVENT_RELEASED)
    {
        M2_str = String("M2:") + String(ACT_PUSH);
        // //对象被按下时触发,每次按下时只触发一次
        Serial2.println(M2_str);
        Serial.println(M2_str);
        TOUCH_DELAY;
    }
}
static void M1_step_slider_event_cb(lv_obj_t *obj, lv_event_t e)
{
    if (e == LV_EVENT_VALUE_CHANGED)
    {
        M1_step = lv_slider_get_value(M1_step_slider);
        lv_label_set_text(M1_step_lab, String(M1_step).c_str());
        if (!M1_sw_state)
        {
            M1_str = String("M1:") + String(M1_step) + "dir:" + String(M1_dir);
            Serial2.println(M1_str);
            Serial.println(M1_str);
        }
        else
        {
            M1_str = String("M1:") + String(0) + "dir:" + String(M1_dir);
            Serial2.println(M1_str);
            Serial.println(M1_str);
        }
        // TOUCH_DELAY;
        delay(50);
    }
}

/*debug*/
// if (millis() - date > 500)
// {
//     date = millis();
//     M1_step++;
//     if (M1_step == 8)
//         M1_step = 1;
//     M1_str = String("M1:") + String(M1_step) + "dir:" + String(M1_dir);
//     Serial2.println(M1_str);
//     delay(50);
//     if (M1_step % 2 == 0)
//         M2_act = ACT_PUSH;
//     else
//         M2_act = ACT_POP;
//     M2_str = String("M2:") + String(M2_act);
//     Serial2.println(M2_str);
//     Serial.println("DIS.Send");
// }
